// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
// SPDX-License-Identifier: MIT

// Package errors 提供结构化的错误处理功能
package errors

import (
	"context"
	"fmt"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
	"time"
	"uos_uwsgi_exporter/pkg/utils"
)

// ErrorType 错误类型枚举
type ErrorType string

const (
	// 连接相关错误
	ErrorTypeConnection ErrorType = "connection"
	ErrorTypeTimeout    ErrorType = "timeout"
	ErrorTypeNetwork    ErrorType = "network"

	// 配置相关错误
	ErrorTypeConfig     ErrorType = "config"
	ErrorTypeValidation ErrorType = "validation"

	// 数据处理错误
	ErrorTypeParser ErrorType = "parser"
	ErrorTypeFormat ErrorType = "format"

	// 系统错误
	ErrorTypeSystem   ErrorType = "system"
	ErrorTypeResource ErrorType = "resource"

	// 业务逻辑错误
	ErrorTypeBusiness ErrorType = "business"
	ErrorTypeAuth     ErrorType = "auth"
)

// Severity 错误严重程度
type Severity string

const (
	SeverityLow      Severity = "low"      // 轻微错误，不影响主要功能
	SeverityMedium   Severity = "medium"   // 中等错误，影响部分功能
	SeverityHigh     Severity = "high"     // 严重错误，影响主要功能
	SeverityCritical Severity = "critical" // 致命错误，服务不可用
)

// StructuredError 结构化错误类型
type StructuredError struct {
	Type       ErrorType              `json:"type"`
	Code       string                 `json:"code"`
	Message    string                 `json:"message"`
	Details    string                 `json:"details,omitempty"`
	Context    map[string]interface{} `json:"context,omitempty"`
	Cause      error                  `json:"-"`
	Timestamp  time.Time              `json:"timestamp"`
	Severity   Severity               `json:"severity"`
	Retryable  bool                   `json:"retryable"`
	Component  string                 `json:"component"`
	Operation  string                 `json:"operation,omitempty"`
	StackTrace string                 `json:"stack_trace,omitempty"`
}

// Error 实现error接口
func (e *StructuredError) Error() string {
	if e.Details != "" {
		return fmt.Sprintf("[%s:%s] %s: %s", e.Type, e.Code, e.Message, e.Details)
	}
	return fmt.Sprintf("[%s:%s] %s", e.Type, e.Code, e.Message)
}

// Unwrap 实现errors.Unwrap接口
func (e *StructuredError) Unwrap() error {
	return e.Cause
}

// WithContext 添加上下文信息
func (e *StructuredError) WithContext(key string, value interface{}) *StructuredError {
	if e.Context == nil {
		e.Context = make(map[string]interface{})
	}
	e.Context[key] = value
	return e
}

// WithOperation 设置操作信息
func (e *StructuredError) WithOperation(operation string) *StructuredError {
	e.Operation = operation
	return e
}

// WithStackTrace 添加堆栈跟踪
func (e *StructuredError) WithStackTrace() *StructuredError {
	buf := make([]byte, 4096)
	n := runtime.Stack(buf, false)
	// 清理堆栈跟踪中的敏感路径信息
	e.StackTrace = SanitizeStackTrace(string(buf[:n]))
	return e
}

// IsRetryable 判断错误是否可重试
func (e *StructuredError) IsRetryable() bool {
	return e.Retryable
}

// GetSeverity 获取错误严重程度
func (e *StructuredError) GetSeverity() Severity {
	return e.Severity
}

// New 创建新的结构化错误
func New(errorType ErrorType, code, message string) *StructuredError {
	return &StructuredError{
		Type:      errorType,
		Code:      code,
		Message:   message,
		Timestamp: time.Now(),
		Severity:  SeverityMedium,
		Retryable: false,
	}
}

// NewSafe 创建新的结构化错误，自动清理敏感路径信息
func NewSafe(errorType ErrorType, code, message string) *StructuredError {
	return &StructuredError{
		Type:      errorType,
		Code:      code,
		Message:   SanitizeErrorMessage(message),
		Timestamp: time.Now(),
		Severity:  SeverityMedium,
		Retryable: false,
	}
}

// Wrap 包装现有错误为结构化错误
func Wrap(err error, errorType ErrorType, code, message string) *StructuredError {
	return &StructuredError{
		Type:      errorType,
		Code:      code,
		Message:   message,
		Cause:     err,
		Timestamp: time.Now(),
		Severity:  SeverityMedium,
		Retryable: false,
	}
}

// WrapSafe 包装现有错误为结构化错误，自动清理敏感路径信息
func WrapSafe(err error, errorType ErrorType, code, message string) *StructuredError {
	return &StructuredError{
		Type:      errorType,
		Code:      code,
		Message:   SanitizeErrorMessage(message),
		Cause:     err,
		Timestamp: time.Now(),
		Severity:  SeverityMedium,
		Retryable: false,
	}
}

// 预定义的错误构造函数

// NewConnectionError 创建连接错误
func NewConnectionError(socket, operation string, cause error) *StructuredError {
	err := Wrap(cause, ErrorTypeConnection, "CONN_FAILED", "Connection failed")
	err.WithContext("socket", socket)
	err.WithOperation(operation)
	err.Severity = SeverityHigh
	err.Retryable = isRetryableConnectionError(cause)
	return err
}

// NewTimeoutError 创建超时错误
func NewTimeoutError(operation string, timeout time.Duration, cause error) *StructuredError {
	err := Wrap(cause, ErrorTypeTimeout, "TIMEOUT", "Operation timeout")
	err.WithOperation(operation)
	err.WithContext("timeout", timeout.String())
	err.Severity = SeverityMedium
	err.Retryable = true
	return err
}

// NewConfigError 创建配置错误
func NewConfigError(field, value, reason string) *StructuredError {
	err := New(ErrorTypeConfig, "CONFIG_INVALID", "Invalid configuration")
	err.WithContext("field", field)
	err.WithContext("value", value)
	err.Details = reason
	err.Severity = SeverityCritical
	err.Retryable = false
	return err
}

// NewParserError 创建解析错误
func NewParserError(format, data string, cause error) *StructuredError {
	err := Wrap(cause, ErrorTypeParser, "PARSE_FAILED", "Failed to parse data")
	err.WithContext("format", format)
	err.WithContext("data_preview", truncateString(data, 100))
	err.Severity = SeverityMedium
	err.Retryable = false
	return err
}

// NewValidationError 创建验证错误
func NewValidationError(field, value, constraint string) *StructuredError {
	err := New(ErrorTypeValidation, "VALIDATION_FAILED", "Validation failed")
	err.WithContext("field", field)
	err.WithContext("value", value)
	err.WithContext("constraint", constraint)
	err.Severity = SeverityMedium
	err.Retryable = false
	return err
}

// NewSystemError 创建系统错误
func NewSystemError(operation string, cause error) *StructuredError {
	err := Wrap(cause, ErrorTypeSystem, "SYSTEM_ERROR", "System operation failed")
	err.WithOperation(operation)
	err.Severity = SeverityHigh
	err.Retryable = isRetryableSystemError(cause)
	return err
}

// NewFileError 创建安全的文件操作错误（自动清理路径信息）
func NewFileError(operation, filePath string, cause error) *StructuredError {
	// 使用新的安全工具进行路径脱敏
	safePath := utils.SafeFilePath(filePath)
	err := WrapSafe(cause, ErrorTypeSystem, "FILE_ERROR", fmt.Sprintf("File operation failed: %s", operation))
	err.WithOperation(operation)
	err.WithContext("file", safePath)
	err.Severity = SeverityMedium
	err.Retryable = false
	return err
}

// NewConfigFileError 创建安全的配置文件错误（自动清理路径信息）
func NewConfigFileError(filePath string, cause error) *StructuredError {
	var message string
	if cause != nil {
		// 使用新的安全工具清理错误消息中的路径信息
		safeErrorMsg := utils.SafeErrorMessage(cause.Error())
		message = fmt.Sprintf("Configuration file error: %s", safeErrorMsg)
	} else {
		message = "Configuration file not found"
	}

	// 使用新的安全工具进行路径脱敏
	safePath := utils.SafeFilePath(filePath)
	err := WrapSafe(cause, ErrorTypeConfig, "CONFIG_FILE_ERROR", message)
	err.WithContext("config_file", safePath)
	err.Severity = SeverityHigh
	err.Retryable = false
	return err
}

// 错误检查辅助函数

// IsConnectionError 检查是否为连接错误
func IsConnectionError(err error) bool {
	var structErr *StructuredError
	if As(err, &structErr) {
		return structErr.Type == ErrorTypeConnection
	}
	return false
}

// IsTimeoutError 检查是否为超时错误
func IsTimeoutError(err error) bool {
	// 检查结构化错误
	var structErr *StructuredError
	if As(err, &structErr) {
		return structErr.Type == ErrorTypeTimeout
	}

	// 检查网络超时错误
	var netErr net.Error
	if As(err, &netErr) {
		return netErr.Timeout()
	}

	// 检查上下文超时
	if err == context.DeadlineExceeded {
		return true
	}

	return false
}

// IsRetryable 检查错误是否可重试
func IsRetryable(err error) bool {
	var structErr *StructuredError
	if As(err, &structErr) {
		return structErr.Retryable
	}

	// 对于非结构化错误，使用启发式判断
	return isRetryableConnectionError(err) || isRetryableSystemError(err)
}

// GetSeverity 获取错误严重程度
func GetSeverity(err error) Severity {
	var structErr *StructuredError
	if As(err, &structErr) {
		return structErr.Severity
	}
	return SeverityMedium
}

// 内部辅助函数

// matchErrorPatterns 通用的错误模式匹配函数
func matchErrorPatterns(err error, patterns []string) bool {
	if err == nil {
		return false
	}

	errStr := strings.ToLower(err.Error())
	for _, pattern := range patterns {
		if strings.Contains(errStr, pattern) {
			return true
		}
	}
	return false
}

// isRetryableConnectionError 判断连接错误是否可重试
func isRetryableConnectionError(err error) bool {
	retryablePatterns := []string{
		"connection refused",
		"network is unreachable",
		"no route to host",
		"timeout",
		"temporary failure",
		"try again",
		"resource temporarily unavailable",
	}
	return matchErrorPatterns(err, retryablePatterns)
}

// isRetryableSystemError 判断系统错误是否可重试
func isRetryableSystemError(err error) bool {
	retryablePatterns := []string{
		"too many open files",
		"resource temporarily unavailable",
		"no space left on device",
		"disk full",
	}
	return matchErrorPatterns(err, retryablePatterns)
}

// truncateString 截断字符串
func truncateString(s string, maxLen int) string {
	if len(s) <= maxLen {
		return s
	}
	return s[:maxLen] + "..."
}

// PathSanitizer 路径清理器配置
type PathSanitizer struct {
	// 敏感路径前缀列表
	SensitivePrefixes []string
	// 是否移除用户家目录路径
	RemoveHomeDir bool
	// 是否移除工作目录路径
	RemoveWorkDir bool
	// 是否移除绝对路径信息
	RemoveAbsolutePaths bool
}

// DefaultPathSanitizer 默认路径清理器
var DefaultPathSanitizer = &PathSanitizer{
	SensitivePrefixes: []string{
		"/home/",
		"/root/",
		"/etc/",
		"/var/",
		"/usr/",
		"/opt/",
		"/tmp/",
		"/sys/",
		"/proc/",
		"/dev/",
	},
	RemoveHomeDir:       true,
	RemoveWorkDir:       true,
	RemoveAbsolutePaths: true,
}

// SanitizePath 清理路径中的敏感信息
func (ps *PathSanitizer) SanitizePath(path string) string {
	if path == "" {
		return path
	}

	// 清理路径
	sanitized := path

	// 首先检查并清理敏感路径前缀（优先级最高）
	for _, prefix := range ps.SensitivePrefixes {
		if strings.HasPrefix(sanitized, prefix) {
			// 只保留文件名，移除敏感路径
			sanitized = filepath.Base(sanitized)
			return sanitized
		}
	}

	// 获取当前工作目录和用户家目录
	var workDir, homeDir string
	if ps.RemoveWorkDir {
		if wd, err := os.Getwd(); err == nil {
			workDir = wd
		}
	}
	if ps.RemoveHomeDir {
		if hd, err := os.UserHomeDir(); err == nil {
			homeDir = hd
		}
	}

	// 替换用户家目录（仅当不在敏感前缀中时）
	if homeDir != "" && strings.HasPrefix(sanitized, homeDir) {
		sanitized = strings.Replace(sanitized, homeDir, "~", 1)
	}

	// 替换当前工作目录（仅当不在敏感前缀中时）
	if workDir != "" && strings.HasPrefix(sanitized, workDir) {
		// 使用相对路径表示
		if rel, err := filepath.Rel(workDir, sanitized); err == nil && !strings.HasPrefix(rel, "..") {
			sanitized = "./" + rel
		}
	}

	// 如果设置了移除绝对路径，将绝对路径转换为相对形式
	if ps.RemoveAbsolutePaths && filepath.IsAbs(sanitized) && sanitized != path {
		sanitized = filepath.Base(sanitized)
	}

	return sanitized
}

// SanitizeErrorMessage 清理错误消息中的敏感路径信息
func (ps *PathSanitizer) SanitizeErrorMessage(message string) string {
	if message == "" {
		return message
	}

	// 使用正则表达式匹配可能的文件路径
	// 匹配绝对路径和相对路径
	pathRegex := regexp.MustCompile(`[/\\]?(?:[a-zA-Z]:[/\\])?(?:[^/\\:\s<>"|*?]+[/\\])*[^/\\:\s<>"|*?\n]+\.[a-zA-Z0-9]+|[/\\](?:[^/\\:\s<>"|*?]+[/\\])*[^/\\:\s<>"|*?\n]*`)

	return pathRegex.ReplaceAllStringFunc(message, func(match string) string {
		// 只清理看起来像文件路径的匹配项
		if strings.Contains(match, "/") || strings.Contains(match, "\\") {
			return ps.SanitizePath(match)
		}
		return match
	})
}

// SanitizeStackTrace 清理堆栈跟踪中的敏感路径信息
func (ps *PathSanitizer) SanitizeStackTrace(stackTrace string) string {
	if stackTrace == "" {
		return stackTrace
	}

	lines := strings.Split(stackTrace, "\n")
	for i, line := range lines {
		// 堆栈跟踪通常包含文件路径和行号
		// 格式例如: /path/to/file.go:123
		if strings.Contains(line, ".go:") {
			// 使用正则表达式匹配文件路径
			pathRegex := regexp.MustCompile(`(/[^:\s]+\.go):(\d+)`)
			lines[i] = pathRegex.ReplaceAllStringFunc(line, func(match string) string {
				parts := strings.Split(match, ":")
				if len(parts) >= 2 {
					path := parts[0]
					lineNum := parts[1]

					// 保留Go标准库路径不变
					if strings.Contains(path, "/go/src/") || strings.Contains(path, "/usr/local/go/") {
						return match
					}

					sanitizedPath := ps.SanitizePath(path)
					return sanitizedPath + ":" + lineNum
				}
				return match
			})
		}
	}

	return strings.Join(lines, "\n")
}

// SanitizePath 使用默认清理器清理路径
func SanitizePath(path string) string {
	return DefaultPathSanitizer.SanitizePath(path)
}

// SanitizeErrorMessage 使用默认清理器清理错误消息
func SanitizeErrorMessage(message string) string {
	return DefaultPathSanitizer.SanitizeErrorMessage(message)
}

// SanitizeStackTrace 使用默认清理器清理堆栈跟踪
func SanitizeStackTrace(stackTrace string) string {
	return DefaultPathSanitizer.SanitizeStackTrace(stackTrace)
}

// As 是 errors.As 的别名，用于类型断言
func As(err error, target interface{}) bool {
	// 简单实现，实际项目中应该使用 errors.As
	if err == nil {
		return false
	}

	switch t := target.(type) {
	case **StructuredError:
		if structErr, ok := err.(*StructuredError); ok {
			*t = structErr
			return true
		}
	case *net.Error:
		if netErr, ok := err.(net.Error); ok {
			*t = netErr
			return true
		}
	}

	return false
}

// ErrorHandler 错误处理器接口
type ErrorHandler interface {
	HandleError(err error, component string) error
}

// DefaultErrorHandler 默认错误处理器
type DefaultErrorHandler struct {
	Logger interface {
		WithError(error) interface {
			Error(string)
			Warn(string)
			Info(string)
		}
		WithField(string, interface{}) interface {
			Error(string)
			Warn(string)
			Info(string)
		}
	}
}

// HandleError 处理错误
func (h *DefaultErrorHandler) HandleError(err error, component string) error {
	if err == nil {
		return nil
	}

	var structErr *StructuredError
	if As(err, &structErr) {
		// 结构化错误的处理
		logger := h.Logger.WithField("component", component)

		// 根据严重程度选择日志级别
		switch structErr.Severity {
		case SeverityCritical, SeverityHigh:
			logger.Error(structErr.Message)
		case SeverityMedium:
			logger.Warn(structErr.Message)
		case SeverityLow:
			logger.Info(structErr.Message)
		}

		return structErr
	}

	// 非结构化错误的处理
	h.Logger.WithField("component", component).Error("Unhandled error")
	return err
}
